package com.gitee.wsl.ext.array

//import okio.ByteString.Companion.encodeUtf8
//import okio.ByteString.Companion.toByteString
import com.gitee.wsl.security.hash.hmacMD5
import com.gitee.wsl.security.hash.hmacSM3
import com.gitee.wsl.security.hash.hmacSha1
import com.gitee.wsl.security.hash.hmacSha256
import com.gitee.wsl.security.hash.hmacSha512
import com.gitee.wsl.security.hash.md4
import com.gitee.wsl.security.hash.md5
import com.gitee.wsl.security.hash.sha1
import com.gitee.wsl.security.hash.sha256
import com.gitee.wsl.security.hash.sha512
import com.gitee.wsl.security.hash.sm3
import kotlinx.io.bytestring.ByteString

//internal fun ByteArray.toOByteString() = toByteString()

fun ByteArray.toByteString() = ByteString(this)

//fun ByteArray.hashMD5toString(): String = toOByteString().md5().hex()
//
//fun ByteArray.hashSHA1toString(): String = toOByteString().sha1().hex()
//
//fun ByteArray.hashSHA256toString(): String = toOByteString().sha256().hex()
//
//fun ByteArray.hashSHA512toString(): String = toOByteString().sha512().hex()

//fun ByteArray.hashHmacSHA1toString(key: String): String = toOByteString().hmacSha1(key.encodeUtf8()).hex()

//fun ByteArray.hashHmacSHA256toString(key: String): String = toOByteString().hmacSha256(key.encodeUtf8()).hex()

//fun ByteArray.hashHmacSHA512toString(key: String): String = toOByteString().hmacSha512(key.encodeUtf8()).hex()

fun ByteArray.hashSM3toString(): String = sm3().toNoPrefixHexString()

fun ByteArray.hashHmacSM3toString(key: String): String = hmacSM3(key.encodeToByteArray()).toNoPrefixHexString()

fun ByteArray.hashMD4toString(): String = md4().toNoPrefixHexString()
fun ByteArray.hashMD5toString(): String = md5().toNoPrefixHexString()

fun ByteArray.hashSHA1toString(): String = sha1().toNoPrefixHexString()

fun ByteArray.hashSHA256toString(): String = sha256().toNoPrefixHexString()

fun ByteArray.hashSHA512toString(): String = sha512().toNoPrefixHexString()

fun ByteArray.hashHmacSHA1toString(key: String): String = hmacSha1(key.encodeToByteArray()).toNoPrefixHexString()

fun ByteArray.hashHmacSHA256toString(key: String): String = hmacSha256(key.encodeToByteArray()).toNoPrefixHexString()

fun ByteArray.hashHmacSHA512toString(key: String): String = hmacSha512(key.encodeToByteArray()).toNoPrefixHexString()

fun ByteArray.hashHmacMD5toString(key: String): String = hmacMD5(key.encodeToByteArray()).toNoPrefixHexString()


internal inline fun <T> contentHashCode(size: Int, gen: (index: Int) -> T): Int {
    var result = 1
    for (n in 0 until size) result = 31 * result + gen(n).hashCode()
    return result
}

internal inline fun hashCoder(count: Int, gen: (index: Int) -> Int): Int {
    var out = 0
    for (n in 0 until count) {
        out *= 7
        out += gen(n)
    }
    return out
}

fun <T> Array<T>.contentHashCode(src: Int, dst: Int): Int =
    hashCoder(dst - src) { this[src + it].hashCode() }

 fun IntArray.contentHashCode(src: Int, dst: Int): Int =
    hashCoder(dst - src) { this[src + it].toInt() }

 fun ShortArray.contentHashCode(src: Int, dst: Int): Int =
    hashCoder(dst - src) { this[src + it].toInt() }

 fun FloatArray.contentHashCode(src: Int, dst: Int): Int =
    hashCoder(dst - src) { this[src + it].toRawBits() }

 fun DoubleArray.contentHashCode(src: Int, dst: Int): Int =
    hashCoder(dst - src) {
        this[src + it].toInt()
    } // Do not want to use Long (.toRawBits) to prevent boxing on JS


@Suppress("NOTHING_TO_INLINE")
inline fun Any.contentHashCodeIfArray() = when(this) {
    is Array<*> -> this.contentHashCode()
    is ByteArray -> this.contentHashCode()
    is ShortArray -> this.contentHashCode()
    is IntArray -> this.contentHashCode()
    is LongArray -> this.contentHashCode()
    is FloatArray -> this.contentHashCode()
    is DoubleArray -> this.contentHashCode()
    is CharArray -> this.contentHashCode()
    is BooleanArray -> this.contentHashCode()
    else -> this.hashCode()
}